#include <stdio.h>
#include <stdlib.h>
#include <alsa/asoundlib.h>

#define PCM_DEVICE "default"

int main(int argc, char *argv[]) {
    unsigned int pcm, tmp; // 移除未使用的dir变量
    unsigned int rate = 44100; // 采样率
    unsigned int channels = 1; // 声道数
    snd_pcm_t *pcm_handle;
    snd_pcm_hw_params_t *params;
    snd_pcm_uframes_t frames;
    char *buff;
    int buff_size; // 移除未使用的loops变量
    FILE *audio_file;

    if (argc < 2) {
        fprintf(stderr, "Usage: %s <raw_audio_file>\n", argv[0]);
        return -1;
    }

    // 打开音频文件
    audio_file = fopen(argv[1], "rb");
    if (!audio_file) {
        perror("Failed to open audio file");
        return -1;
    }

    // 打开PCM设备
    if (snd_pcm_open(&pcm_handle, PCM_DEVICE, SND_PCM_STREAM_PLAYBACK, 0) < 0) {
        fprintf(stderr, "ERROR: Can't open \"%s\" PCM device.\n", PCM_DEVICE);
        return -1;
    }

    // 分配默认参数
    snd_pcm_hw_params_alloca(&params);
    snd_pcm_hw_params_any(pcm_handle, params);

    // 设置参数
    if (snd_pcm_hw_params_set_access(pcm_handle, params, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
        fprintf(stderr, "ERROR: Can't set interleaved mode.\n");
        return -1;
    }
    if (snd_pcm_hw_params_set_format(pcm_handle, params, SND_PCM_FORMAT_S16_LE) < 0) {
        fprintf(stderr, "ERROR: Can't set format.\n");
        return -1;
    }
    if (snd_pcm_hw_params_set_channels(pcm_handle, params, channels) < 0) {
        fprintf(stderr, "ERROR: Can't set channels number.\n");
        return -1;
    }
    if (snd_pcm_hw_params_set_rate_near(pcm_handle, params, &rate, 0) < 0) {
        fprintf(stderr, "ERROR: Can't set rate.\n");
        return -1;
    }

    // 应用参数
    if (snd_pcm_hw_params(pcm_handle, params) < 0) {
        fprintf(stderr, "ERROR: Can't set harware parameters.\n");
        return -1;
    }

    // 获取缓冲区大小
    snd_pcm_hw_params_get_period_size(params, &frames, 0);
    buff_size = frames * channels * 2 /* 2 -> sample size */;
    buff = (char *) malloc(buff_size);

    snd_pcm_hw_params_get_period_time(params, &tmp, NULL);

    // 读取并播放音频
    while ((pcm = fread(buff, 1, buff_size, audio_file)) > 0) {
        if (pcm != buff_size) {
            snd_pcm_prepare(pcm_handle);
        }
        if (snd_pcm_writei(pcm_handle, buff, frames) == -EPIPE) {
            fprintf(stderr, "XRUN.\n");
            snd_pcm_prepare(pcm_handle);
        } else if (pcm < 0) {
            fprintf(stderr, "ERROR: Can't write to PCM device. %s\n", snd_strerror(pcm));
        }
    }

    // 清理和关闭操作
    free(buff);
    snd_pcm_drain(pcm_handle);
    snd_pcm_close(pcm_handle);
    fclose(audio_file);

    return 0;
}